using System.Linq;
using CriWare;
using CriWare.CriTimeline.Mana;
using IQIGame.Onigao.Game;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;

namespace IQIGame.Onigao.GamePlay
{
    [TrackColor(0.855f, 0.8623f, 0.87f)]
    [TrackBindingType(typeof(CriManaMovieMaterialBase))]
    [TrackClipType(typeof(CriManaClipBase))]
    public class CriwareVideoTrack : CriManaTrack
    {
        public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
        {
            var mixer = ScriptPlayable<CriwareVideoMixedBehaviour>.Create(graph, inputCount);
            var director = go.GetComponent<PlayableDirector>();
            if (director != null)
            {
                CriManaMovieMaterialBase boundMovieMaterial = director.GetGenericBinding(this) as CriManaMovieMaterialBase;
                CriManaMixerBehaviour bh = mixer.GetBehaviour();
                bh.m_clips = GetClips() as TimelineClip[];
                if (bh.m_clips == null)
                {
                    // Fallback to Linq.ToArray if failed in casting
                    bh.m_clips = GetClips().ToArray();
                }
                bh.m_PlayableDirector = director;
                bh.m_frameSync = this.frameSync;

                foreach (var clip in bh.m_clips)
                {
                    var clipAsset = (clip.asset as CriManaClipBase);
                    clipAsset.m_clip = clip;
                    clip.displayName = clipAsset.MovieName;
                }

                /* make sure binding is unique across all tracks */
                if (boundMovieMaterial != null)
                {
                    var movieInstanceID = boundMovieMaterial.GetInstanceID();

                    if (bindDict.ContainsKey(movieInstanceID) && bindDict[movieInstanceID] != guid)
                    {
                        director.SetGenericBinding(this, null);
                        boundMovieMaterial = null;
                        Debug.LogWarning("[CRIWARE] Binding the same movie controller to multiple tracks is not allowed. Operation has been cancelled.");
                    }
                    else
                    {
                        if (bindDict.ContainsKey(movieInstanceID))
                        {
                            try
                            {
                                bindDict.Remove(movieInstanceID);
                            }
                            catch
                            {
                                Debug.LogError("[CRIWARE] Timeline / Mana: (Internal) Binding dictionary logic error");
                            }
                        }
                        RemoveTrackFromBindDict(this);
                        try
                        {
                            bindDict.Add(movieInstanceID, guid);
                        }
                        catch
                        {
                            Debug.LogError("[CRIWARE] Timeline / Mana: (Internal) Binding dictionary logic error");
                        }
                    }
                }
                else
                {
                    RemoveTrackFromBindDict(this);
                }

                bh.m_boundMovieMaterial = boundMovieMaterial;
                bh.m_CheckPosWithinClip = checkPosWithinClip;
            }
            return mixer;
        }
    }
}